typedef unsigned long u;
typedef signed long s;

enum stag {
  tbool = 1, // value: #f, #t
  tnumb = 2, // ivalue: number
  tchar = 3, // ivalue: char
  tsymb = 4, // value: symbol table ref
  tcons = 5, // value: cons ref
  tstrn = 6, // value: string ref
  tvect = 7, // value: vec ref
  tclos = 8, // value: closure ref
  tnull = 9,
  teof = 10,

  tlabl = 11, // value: label
};

typedef struct {
  enum stag tag;
  union {
    u value;
    s ivalue;
  } data;
} sdata;

#define SDBOOL(t) (sdata){.tag = tbool, .data.ivalue = t}
#define SDSYMB(t) (sdata){.tag = tsymb, .data.value = intern(t)}
#define SDNUMB(t) (sdata){.tag = tnumb, .data.ivalue = t}
#define SDCHAR(t) (sdata){.tag = tchar, .data.ivalue = t}
#define SDNULL() (sdata){.tag = tnull}
#define SDEOF() (sdata){.tag = teof}

// http://c.learncodethehardway.org/book/ex20.html
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__); exit(-1)
